﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.IO;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;

namespace AudioCore.Common
{
    public class ImageUtils
    {
        public static Image DownloadImage(string url)
        {
            try
            {
                //WebClient client = new WebClient();
                //Stream stream = client.OpenRead(url);
                //Image bitmap = new Bitmap(stream);
                //stream.Flush();
                //stream.Close();
                //return bitmap;

                // Create the requests.
                WebRequest requestPic = WebRequest.Create(url);

                WebResponse responsePic = requestPic.GetResponse();

                Image webImage = Image.FromStream(responsePic.GetResponseStream());

                return webImage;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return null;
            }
        }

        public static Size GetThumbnailSize(Size orignalImageSize, Size frameThumbnailSize)
        {
            if (orignalImageSize.Width <= frameThumbnailSize.Width &&
                orignalImageSize.Height <= frameThumbnailSize.Height)
                return orignalImageSize;

            Size actualSize = new Size();
            float ratioShow = (float)frameThumbnailSize.Width / (float)frameThumbnailSize.Height;
            float ratioImage = (float)orignalImageSize.Width / (float)orignalImageSize.Height;
            float ratio;
            if (ratioImage >= ratioShow)
            {
                ratio = (float)orignalImageSize.Width / (float)frameThumbnailSize.Width;
                actualSize.Width = frameThumbnailSize.Width;
                actualSize.Height = (int)Math.Round(orignalImageSize.Height / ratio, 0);
            }
            else
            {
                ratio = (float)orignalImageSize.Height / (float)frameThumbnailSize.Height;
                actualSize.Height = frameThumbnailSize.Height;
                actualSize.Width = (int)Math.Round(orignalImageSize.Width / ratio, 0);
            }
            if (actualSize.Width == 0)
                actualSize.Width = 1;
            if (actualSize.Height == 0)
                actualSize.Height = 1;
            return actualSize;
        }

        public static Image Resize(Image originalImage, Size thumbnailSize)
        {
            try
            {
                Size originalSize = new Size(originalImage.Width, originalImage.Height);
                Size size = GetThumbnailSize(originalSize, thumbnailSize);

                Image result = new Bitmap(originalImage, size.Width, size.Height);
                return result;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        //public static byte[] GetBytesFromBitmap(Image bitmap)
        //{
        //    MemoryStream ms = new MemoryStream();
        //    bitmap.Save(ms, ImageFormat.Jpeg);
        //    return ms.ToArray();
        //}

        //[CLSCompliant(false)]
        //public static Bitmap IBitmapImageToBitmap(IBitmapImage imageBitmap)
        //{
        //    try
        //    {
        //        Size size;
        //        imageBitmap.GetSize(out size);
        //        RECT rect = new RECT(0, 0, size.Width, size.Height);
        //        // Rectangle rect = new Rectangle(0, 0, textSizeF.Width, textSizeF.Height);
        //        BitmapDataInternal lockedBitmapData = new BitmapDataInternal();
        //        // System.Drawing.Imaging.BitmapData lockedBitmapData = new System.Drawing.Imaging.BitmapData();
        //        imageBitmap.LockBits(rect, 0, PixelFormat.Format24bppRgb, ref lockedBitmapData);
        //        Bitmap bitmap = new Bitmap(lockedBitmapData.Width, lockedBitmapData.Height, lockedBitmapData.PixelFormat);
        //        System.Drawing.Imaging.BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, lockedBitmapData.PixelFormat);
        //        CopyMemory(bitmapdata.Scan0, lockedBitmapData.Scan0, lockedBitmapData.Height * lockedBitmapData.Stride);
        //        imageBitmap.UnlockBits(ref lockedBitmapData);
        //        bitmap.UnlockBits(bitmapdata);
        //        return bitmap;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw ex;
        //    }
        //}

        //internal static void CopyMemory(IntPtr pDst, IntPtr pSrc, int cbSize)
        //{
        //    byte[] destination = new byte[0x10000];
        //    while (cbSize > 0x10000)
        //    {
        //        Marshal.Copy(pSrc, destination, 0, 0x10000);
        //        Marshal.Copy(destination, 0, pDst, 0x10000);
        //        cbSize -= 0x10000;
        //        pDst = (IntPtr)(((int)pDst) + 0x10000);
        //        pSrc = (IntPtr)(((int)pSrc) + 0x10000);
        //    }
        //    Marshal.Copy(pSrc, destination, 0, cbSize);
        //    Marshal.Copy(destination, 0, pDst, cbSize);
        //}

        //public static Image CreateThumbnail(byte[] buffer, Size thumbnailSize)
        //{
        //    try
        //    {
        //        IImagingFactory factory = (IImagingFactory)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("327ABDA8-072B-11D3-9D7B-0000F81EF32E")));
        //        IImage img;
        //        factory.CreateImageFromBuffer(buffer, (uint)buffer.Length, BufferDisposalFlag.BufferDisposalFlagNone, out img);

        //        // Get textSizeF
        //        ImageInfo imgInfo;
        //        img.GetImageInfo(out imgInfo);
        //        Size actualSize = GetThumbnailSize(new Size((int)imgInfo.Width, (int)imgInfo.Height), thumbnailSize);

        //        // Create thumbnail
        //        IBitmapImage imgB;
        //        factory.CreateBitmapFromImage(img,
        //            (uint)actualSize.Width,
        //            (uint)actualSize.Height,
        //            PixelFormatID.PixelFormat24bppRGB,
        //            InterpolationHint.InterpolationHintDefault,
        //            out imgB);
        //        Image image = ImageUtils.IBitmapImageToBitmap(imgB);
        //        return image;
        //    }
        //    catch (OutOfMemoryException ex)
        //    {
        //        throw ex;
        //    }
        //    catch (Exception ex)
        //    {
        //        throw ex;
        //    }
        //}

        public Image Resize(Image img, int percentage)
        {
            //get the height and width of the image
            int originalW = img.Width;
            int originalH = img.Height;

            //get the new size based on the percentage change
            int resizedW = (int)(originalW * percentage);
            int resizedH = (int)(originalH * percentage);

            //create a new Bitmap the size of the new image
            Bitmap bmp = new Bitmap(resizedW, resizedH);
            //create a new graphic from the Bitmap
            Graphics graphic = Graphics.FromImage((Image)bmp);
            graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
            //draw the newly resized image
            graphic.DrawImage(img, 0, 0, resizedW, resizedH);
            //dispose and free up the resources
            graphic.Dispose();
            //return the image
            return (Image)bmp;
        }

        private static string PRE_COMPANY_NAME = @"AutoEnter";
        private static int MAX_NUMBER_OF_ID = 8;
        private static string BRIDGE_CHAR = "_";
        private static string FILE_PATTERN = "*.jp*g";
        private static string FOLDER_ORIGINAL = "Original";

        #region Public methods
        public static string GetUrlImage(string rootFolder, int imageID, int width, int height)
        {
            return "";
        }

        /// <summary>
        /// For all files in a folder, Genarate to specify sizes of image.
        /// </summary>
        /// <param name="inDir">Dir contain files to resize (Ex: GirlXinh/original)</param>
        /// <param name="sizes">List of size to generate to.</param>
        public static void GenSizedImages(string inDir, Size[] sizes)
        {
            // Loop all size
            if (sizes != null && sizes.Length > 0)
            {
                foreach (var file in Directory.GetFiles(inDir))
                {
                    ImageUtils.GenSizedImage(file, sizes);
                }
            }
        }
        /// <summary>
        /// For 1 file, Genarate to specify sizes of image.
        /// </summary>
        /// <param name="inDir">Fullpath to a file.</param>
        /// <param name="sizes">List of size to generate to.</param>
        public static void GenSizedImage(string filePath, Size[] sizes)
        {
            foreach (var size in sizes)
            {
                // Genarate a size
                GenSizedImage(filePath, size);
            }
        }

        public static void GenSizedImage(string inPath, string outPath, Size size)
        {
            ImageProcessing.ResizeFromFile(inPath, outPath, size);
        }

        public static System.Drawing.Image ResizeImage(System.Drawing.Image img, Size size)
        {
            return ImageProcessing.ResizeImage(img, size);
        }

        /// <summary> 
        /// Saves an image as a jpeg image, with the given quality 
        /// </summary> 
        /// <param name="path">Path to which the image would be saved.</param> 
        // <param name="quality">An integer from 0 to 100, with 100 being the 
        /// highest quality</param> 
        public static void SaveJpeg(string path, System.Drawing.Image img, int quality)
        {
            if (quality < 0 || quality > 100)
                throw new ArgumentOutOfRangeException("quality must be between 0 and 100.");


            // Encoder parameter for image quality 
            EncoderParameter qualityParam =
                new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Jpeg image codec 
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            img.Save(path, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Saves an image as a jpeg image, with the given quality 
        /// </summary> 
        /// <param name="stream">Stream to which the image would be saved.</param> 
        // <param name="quality">An integer from 0 to 100, with 100 being the 
        /// highest quality</param> 
        public static void SaveJpeg(System.IO.Stream stream, System.Drawing.Image img, int quality)
        {
            if (quality < 0 || quality > 100)
                throw new ArgumentOutOfRangeException("quality must be between 0 and 100.");


            // Encoder parameter for image quality 
            EncoderParameter qualityParam =
                new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
            // Jpeg image codec 
            ImageCodecInfo jpegCodec = GetEncoderInfo("image/jpeg");

            EncoderParameters encoderParams = new EncoderParameters(1);
            encoderParams.Param[0] = qualityParam;

            img.Save(stream, jpegCodec, encoderParams);
        }

        /// <summary> 
        /// Returns the image codec with the given mime type 
        /// </summary> 
        private static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            // Get image codecs for all image formats 
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

            // Find the correct image codec 
            for (int i = 0; i < codecs.Length; i++)
                if (codecs[i].MimeType == mimeType)
                    return codecs[i];
            return null;
        }

        #endregion // Public methods

        #region Private methods
        /// <summary>
        /// Generate a image by size.
        /// </summary>
        /// <param name="inPath">Image filepath to resize. This file must whithin "original" folder.</param>
        /// <param name="size">Size to resize.</param>
        private static void GenSizedImage(string inPath, Size size)
        {
            if (size.Width > 0 && size.Height > 0)
            {
                string outPath = MakeFilePathFromSize(inPath, size);
                ImageProcessing.ResizeFromFile(inPath, outPath, size);
            }
        }
        /// <summary>
        /// Make file path follow by inputted image size.
        /// Ex: orgFileName = C:\HotGirl\Original\xxxx.jpg
        ///     size = (100, 100)
        ///     =>> result: C:\HotGirl\Original\100x100\xxxx.jpg
        /// </summary>
        /// <param name="orgFileName"></param>
        /// <param name="size"></param>
        /// <returns></returns>
        private static string MakeFilePathFromSize(string orgFileName, Size size)
        {
            string[] arr = orgFileName.Split('\\');
            string outFile = string.Empty;
            for (int i = 0; i < arr.Length - 2; i++)
            {
                outFile += arr[i] + @"\";
            }
            outFile += size.Width + "x" + size.Height;
            if (!Directory.Exists(outFile))
            {
                Directory.CreateDirectory(outFile);
            }
            outFile += @"\" + arr[arr.Length - 1];
            return outFile;
        }
        /// <summary>
        /// Standardize file name.
        /// Ex: dbID = 1984
        ///     catName = HotGirl
        ///     =>> result: AutoEnter_HotGirl_0001986 (Note: this don't include extension)
        /// </summary>
        /// <param name="dbID">ID of image file in DB.</param>
        /// <param name="catName">Category name.</param>
        /// <returns>Standardized file name</returns>
        private static string StandardizeFileName(int dbID, string catName)
        {
            string strFormat = string.Format("D{0}", MAX_NUMBER_OF_ID);
            return PRE_COMPANY_NAME + BRIDGE_CHAR + catName + BRIDGE_CHAR + dbID.ToString(strFormat);
        }
        /// <summary>
        /// Convert from size (in string) to Size object.
        /// </summary>
        /// <param name="size">Size in string (Ex: "128x128"(</param>
        /// <returns>Size object.</returns>
        internal static Size ConvertToSizeFromString(string size)
        {
            Size s = new Size();
            string[] arr = size.Split('x');
            s.Width = Convert.ToInt32(arr[0]);
            s.Height = Convert.ToInt32(arr[1]);
            return s;
        }
        #endregion //Private methods
    }

}
